package org.devocean.groupbuying.service.impl;

import java.util.Calendar;
import java.util.List;
import org.devocean.groupbuying.dao.DealDAO;
import org.devocean.groupbuying.dao.ExploredDAO;
import org.devocean.groupbuying.dao.MerchantDAO;
import org.devocean.groupbuying.dao.ProductDAO;
import org.devocean.groupbuying.domain.ArticlesLocalization;
import org.devocean.groupbuying.domain.Deal;
import org.devocean.groupbuying.domain.Discount;
import org.devocean.groupbuying.domain.Explored;
import org.devocean.groupbuying.domain.Formula;
import org.devocean.groupbuying.domain.Merchant;
import org.devocean.groupbuying.domain.Plan;
import org.devocean.groupbuying.domain.Product;
import org.devocean.groupbuying.domain.Promotion;
import org.devocean.groupbuying.service.ExploredService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class ExploredServiceImpl implements ExploredService {

	@Autowired
	private ExploredDAO exploredDAO;

	@Autowired
	private ProductDAO productDAO;

	@Autowired
	private DealDAO dealDAO;
	
	@Autowired 
	private MerchantDAO merchantDAO;

	public List<Explored> getAllExploreds() {
		return exploredDAO.findAllExploreds();
	}

	public List<Explored> getAllExploreds(String lang) {
		return exploredDAO.findAllExploreds(lang);
	}

	public long countExploreds() {
		return exploredDAO.countExploreds();
	}

	public long countExploreds(String lang) {
		return exploredDAO.countExploreds(lang);
	}

	public List<Explored> getExploredsEntries(int firstResult, int maxResults) {
		return exploredDAO.findExploredsEntries(firstResult, maxResults);
	}

	public List<Explored> getExploredsEntries(String lang, int firstResult,
			int maxResults) {
		return exploredDAO.findExploredsEntries(lang, firstResult, maxResults);
	}

	public List<Explored> getExploredsEntriesByDate(String lang,
			int firstResult, int maxResults, String order) {
		return exploredDAO.findExploredsEntriesByDate(lang, firstResult,
				maxResults, order);
	}

	public List<Explored> getExploredsEntriesByRating(String lang,
			int firstResult, int maxResults, String order) {
		return exploredDAO.findExploredsEntriesByRating(lang, firstResult,
				maxResults, order);
	}

	public List<Explored> getExploredsEntriesWithDeals(String lang,
			int firstResult, int maxResults, String order) {
		return exploredDAO.findExploredsEntriesWithDeals(lang, firstResult,
				maxResults, order);
	}

	public Explored getExploredById(int id) {
		return exploredDAO.findExploredById(id);
	}

	public Explored getExploredById(String lang, int id) {
		return exploredDAO.findExploredById(lang, id);
	}

	public void deleteExplored(int id) {
		exploredDAO.deleteExplored(id);
	}

	public Explored addOrUpdateExplored(Explored explored) {
		if (explored.getExploredID() == null) {
			return exploredDAO.saveExplored(explored);
		} else {
			return exploredDAO.updateExplored(explored);
		}
	}

	// @Async
	public Explored addOrUpdateExplored(Deal deal) {

		Explored explored = exploredDAO.findExploredByProduct(deal.getProduct()
				.getProductID());

		if (deal.getDealID() == null) {
			explored.setDate(deal.getStartDate());
		}

		upToDateExplored(explored);

		return addOrUpdateExplored(explored);
	}

	// @Async
	public Explored addOrUpdateExplored(Promotion promotion) {
		Explored explored = exploredDAO.findExploredByProduct(promotion
				.getPlan().getProduct().getProductID());
		if (promotion.getPromotionID() == null) {
			explored.setDate(promotion.getStartDate());

		}
		//upToDateExplored(explored);
		return addOrUpdateExplored(explored);
	}

	// @Async
	public Explored addOrUpdateExplored(Product product) {
		Explored explored = exploredDAO.findExploredByProduct(product
				.getProductID());
		if (explored == null) {
			explored = new Explored();
			explored.setClaims(0);
		}

		explored.setProduct(product);
		explored.setProductLocalization(product.getArticlesLocalization());
		explored.setDate(Calendar.getInstance().getTime());
		Merchant merchant = merchantDAO.findMerchantById(product.getMerchant().getMerchantID());
		explored.setMerchantMedia(merchant
				.getArticlesLocalization().getMediaLocalizations().iterator()
				.next());
		explored.setMedia(product.getArticlesLocalization()
				.getMediaLocalizations().iterator().next());
		upToDateExplored(explored);
		return addOrUpdateExplored(explored);
	}

	// @Async
	public Explored addOrUpdateExplored(Plan plan) {
		Explored explored = exploredDAO.findExploredByProduct(plan.getProduct()
				.getProductID());
		if (explored == null) {
			explored = new Explored();
			explored.setClaims(0);
		}

		explored.setDate(Calendar.getInstance().getTime());

		upToDateExplored(explored);
		return addOrUpdateExplored(explored);
	}

	public List<Explored> getExploredByMerchants(Integer merchantID, String lang) {

		return exploredDAO.findExploredByMerchants(merchantID, lang);
	}

	// @Async
	public Explored addOrUpdateExplored(Formula formula) {
		Explored explored = exploredDAO.findExploredByProduct(formula.getPlan()
				.getProduct().getProductID());
		if (explored == null) {
			explored = new Explored();
			explored.setClaims(0);
		}

		explored.setDate(Calendar.getInstance().getTime());

		upToDateExplored(explored);
		return addOrUpdateExplored(explored);
	}

	public Explored upToDateExplored(Explored explored) {

		Double value = 1000000.;
		Double discountedValue = 0.;
		String frequency = "";
		String choice = "";

		for (Deal deal : explored.getProduct().getDeals()) {
			if (deal.getStatus().equals("pending")
					|| deal.getStatus().equals("active")) {
				System.out.println("deals on");
				for (Discount d : deal.getDiscounts()) {
					// set discounted value
					d.getFormula().setDiscounted(d.getDiscountValue());
					d.getFormula().setDate(d.getDeal().getExpireDate());
					if (d.getFormula().getPrice() < value
							&& d.getFormula().getPrice() > 0) {
						System.out.println("formula found");
						System.out.println(d.getFormula());
						System.out.println("Deal : affecting values");
						value = d.getFormula().getPrice();
						System.out.println("value = " + value);
						discountedValue = d.getDiscountPrice();
						System.out.println("discounted value = "
								+ discountedValue);

						// frequency and choice
						frequency = d.getFormula().getFrequency();
						choice = d.getFormula().getChoice();
					}
				}
			}

		}

		// If not overwritten by deals
		if (discountedValue == 0) {
			for (Plan plan : explored.getProduct().getPlans()) {
				for (Promotion promotion : plan.getPromotions()) {
					if (Calendar.getInstance().getTime()
							.before(promotion.getExpireDate())) {
						System.out.println("promotion found");
						for (Formula f : promotion.getPlan().getFormulas()) {
							System.out.println("formula found");
							System.out.println(f);
							// set discounted value
							f.setDate(promotion.getExpireDate());
							if (promotion.getDiscount() != 0) {
								// based on Discount %
								/* (double) Math.round( */
								f.setDiscounted((double) Math.round(f
										.getPrice()
										- (f.getPrice()
												* promotion.getDiscount() / 100)));
							} else if (promotion.getDiscounted() != 0) {
								// based on Discount $
								f.setDiscounted((double) Math.round(f
										.getPrice() - promotion.getDiscounted()));
								if (f.getDiscounted() < 0) {
									f.setDiscounted(0.);
								}
							}

							if (f.getPrice() < value && f.getPrice() > 0) {
								System.out
										.println("Promotions : affecting values");
								System.out.println(promotion);
								value = f.getPrice();
								// frequency and choice
								frequency = f.getFrequency();
								choice = f.getChoice();
								if (promotion.getDiscount() != 0) {
									// based on Discount %
									/* (double) Math.round( */
									discountedValue = (double) Math
											.round(f.getPrice()
													- (f.getPrice()
															* promotion
																	.getDiscount() / 100));
									System.out.println("discounted value = "
											+ discountedValue);
								} else if (promotion.getDiscounted() != 0) {
									// based on Discount $
									discountedValue = (double) Math.round(f
											.getPrice()
											- promotion.getDiscounted());
									System.out.println("discounted value = "
											+ discountedValue);

								}
							}
						}
					}
				}
			}
		}

		// If not overwritten by deals or promotions
		if (discountedValue == 0) {
			System.out.println("no deals no promotions");
			for (Plan plan : explored.getProduct().getPlans()) {
				for (Formula f : plan.getFormulas()) {
					f.setDiscounted(0.);
					if (f.getPrice() < value && f.getPrice() > 0) {
						System.out.println("Plan : affecting values");
						System.out.println("formula found");
						System.out.println(f);
						value = f.getPrice();
						// frequency and choice
						frequency = f.getFrequency();
						choice = f.getChoice();
						System.out.println("value = " + value);
						discountedValue = 0.;
						System.out.println("discounted value = "
								+ discountedValue);
					}
				}
			}
		}
		if (value == 1000000) {
			value = 0.;
		}

		explored.setPrice(value);
		explored.setFrequency(frequency);
		explored.setChoice(choice);
		if (discountedValue < 0) {
			discountedValue = 0.;
		}
		explored.setDiscountedPrice(discountedValue);

		return explored;
	}

	public List<Explored> getExploredsEntries(String lang, int firstResult,
			int maxResults, Integer categorie) {
		return exploredDAO.findExploredsEntries(lang, firstResult, maxResults,
				categorie);
	}

	public Explored getExploredByProduct(int id) {
		// TODO Auto-generated method stub
		return exploredDAO.findExploredByProduct(id);
	}

}
